"""
回滚相关的Celery任务
"""

import asyncio
from typing import Dict, Any

from celery import current_task
from .celery import celery
from services.rollback_service import rollback_service
from database import AsyncSessionLocal
from utils.logger import get_logger

logger = get_logger(__name__)


@celery.task(bind=True, max_retries=3)
def rollback_execution(self, execution_id: int) -> Dict[str, Any]:
    """
    回滚执行

    Args:
        execution_id: 执行记录ID

    Returns:
        回滚结果
    """
    task_id = current_task.request.id

    logger.info(
        "开始回滚执行",
        execution_id=execution_id,
        task_id=task_id
    )

    try:
        # 运行异步任务
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            result = loop.run_until_complete(
                _rollback_execution_async(execution_id)
            )
            return result
        finally:
            loop.close()

    except Exception as e:
        logger.error(
            "执行回滚失败",
            execution_id=execution_id,
            error=str(e)
        )
        raise


async def _rollback_execution_async(execution_id: int) -> Dict[str, Any]:
    """异步回滚执行"""
    async with AsyncSessionLocal() as db:
        rollback_result = await rollback_service.rollback_execution(
            execution_id=execution_id,
            db=db
        )

        return {
            "execution_id": execution_id,
            "rollback_execution_id": rollback_result["rollback_execution_id"],
            "status": rollback_result["status"],
            "success_count": rollback_result["success_count"],
            "failure_count": rollback_result["failure_count"],
            "total_count": rollback_result["total_count"],
            "rollback_results": rollback_result["rollback_results"]
        }


@celery.task
def can_rollback(execution_id: int) -> Dict[str, Any]:
    """
    检查是否可以回滚

    Args:
        execution_id: 执行记录ID

    Returns:
        检查结果
    """
    logger.info("检查回滚条件", execution_id=execution_id)

    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            result = loop.run_until_complete(
                rollback_service.can_rollback(execution_id)
            )
            return result
        finally:
            loop.close()

    except Exception as e:
        logger.error("检查回滚条件失败", execution_id=execution_id, error=str(e))
        return {
            "can_rollback": False,
            "reason": f"检查失败: {str(e)}",
            "execution_id": execution_id
        }


@celery.task
def get_rollback_history(execution_id: int) -> Dict[str, Any]:
    """
    获取回滚历史

    Args:
        execution_id: 执行记录ID

    Returns:
        回滚历史
    """
    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            result = loop.run_until_complete(
                rollback_service.get_rollback_history(execution_id)
            )
            return result
        finally:
            loop.close()

    except Exception as e:
        logger.error("获取回滚历史失败", execution_id=execution_id, error=str(e))
        return {
            "execution_id": execution_id,
            "rollback_history": [],
            "error": str(e)
        }


@celery.task
def batch_rollback(execution_ids: list) -> Dict[str, Any]:
    """
    批量回滚

    Args:
        execution_ids: 执行记录ID列表

    Returns:
        批量回滚结果
    """
    logger.info("开始批量回滚", execution_count=len(execution_ids))

    try:
        results = []

        for execution_id in execution_ids:
            try:
                # 调用回滚任务
                result = rollback_execution.delay(execution_id)
                results.append({
                    "execution_id": execution_id,
                    "task_id": result.id,
                    "status": "queued"
                })
            except Exception as e:
                results.append({
                    "execution_id": execution_id,
                    "status": "error",
                    "error": str(e)
                })

        return {
            "status": "completed",
            "total_executions": len(execution_ids),
            "queued_count": len([r for r in results if r.get("status") == "queued"]),
            "error_count": len([r for r in results if r.get("status") == "error"]),
            "results": results
        }

    except Exception as e:
        logger.error("批量回滚失败", error=str(e))
        return {
            "status": "error",
            "error": str(e),
            "total_executions": len(execution_ids)
        }


@celery.task
def auto_rollback_on_failure(execution_id: int) -> Dict[str, Any]:
    """
    失败时自动回滚

    Args:
        execution_id: 执行记录ID

    Returns:
        自动回滚结果
    """
    logger.info("开始自动回滚", execution_id=execution_id)

    try:
        # 先检查是否可以回滚
        can_check = can_rollback.delay(execution_id)
        can_result = can_check.get()

        if not can_result.get("can_rollback", False):
            logger.info(
                "不满足自动回滚条件",
                execution_id=execution_id,
                reason=can_result.get("reason", "未知原因")
            )
            return {
                "execution_id": execution_id,
                "status": "skipped",
                "reason": can_result.get("reason", "不满足回滚条件")
            }

        # 执行回滚
        rollback_result = rollback_execution.delay(execution_id)

        logger.info(
            "自动回滚已调度",
            execution_id=execution_id,
            rollback_task_id=rollback_result.id
        )

        return {
            "execution_id": execution_id,
            "status": "scheduled",
            "rollback_task_id": rollback_result.id,
            "reason": can_result.get("reason", "满足回滚条件")
        }

    except Exception as e:
        logger.error("自动回滚失败", execution_id=execution_id, error=str(e))
        return {
            "execution_id": execution_id,
            "status": "error",
            "error": str(e)
        }


@celery.task
def cleanup_rollback_cache() -> Dict[str, Any]:
    """
    清理回滚缓存

    Returns:
        清理结果
    """
    try:
        logger.info("开始清理回滚缓存")

        # TODO: 实现回滚缓存清理逻辑
        # 例如：清理临时克隆的回滚仓库目录

        logger.info("回滚缓存清理完成")
        return {"status": "success", "message": "回滚缓存清理完成"}

    except Exception as e:
        logger.error("回滚缓存清理失败", error=str(e))
        return {"status": "failure", "error": str(e)}